#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>

#include "common.h"
#include "constants.h"
#include "../utils/concurrent.h"

const char* SEG_START_FLAG="!&";
const char* SEG_END_FLAG="!#";

struct sockaddr_in create_sockaddr(in_addr_t ip,u_int16_t port)
{
	struct sockaddr_in sockaddr;
	sockaddr.sin_family=AF_INET;
	sockaddr.sin_addr.s_addr=ip;
	sockaddr.sin_port=htons(port);
	return sockaddr;
}


int send_data(int connection,const char* data,int length){
  	int ret=1;
	//send !&
	if(send(connection,SEG_START_FLAG,strlen(SEG_START_FLAG),0)<0){
		ret=-1;
	}

	//send data
	if(send(connection,data,length,0)<0){
		ret=-1;
	}

	//send !#
	if(send(connection,SEG_END_FLAG,strlen(SEG_END_FLAG),0)<0){
		ret=-1;
	}
	return ret;
}


typedef enum head_state{
	SEG_HEAD1,
	SEG_HEAD2,
	SEG_HEADEND,
}head_state_t;

int recv_head(int connection)
{
	head_state_t state=SEG_HEAD1;
	int ret=1;
	while(state!=SEG_HEADEND)
	{
		char c;
		if(recv(connection,&c,1,0) <= 0)
		{
			ret = -1;
			break;
		}
		switch(state)
		{
			case SEG_HEAD1:
			{
				if(c=='!')
					state=SEG_HEAD2;
				break;
			}
			case SEG_HEAD2:
			{
				if(c=='&')
					state=SEG_HEADEND;
				else if(c != '!')
					state=SEG_HEAD1;
				break;
			}
			default:
				break;
		}
	}
	return ret;
}


typedef enum tail_state{
	SEG_TAIL1,
	SEG_TAIL2,
	SEG_TAILEND,
}tail_state_t;

int recv_tail(int connection)
{
	tail_state_t state=SEG_TAIL1;
	int ret=1;
	while(state!=SEG_TAILEND)
	{
		char c;
		if(recv(connection,&c,1,0) <= 0)
		{
			ret = -1;
			break;
		}
		switch(state)
		{
			case SEG_TAIL1:
			{
				if(c=='!')
					state=SEG_TAIL2;
				break;
			}
			case SEG_TAIL2:
			{
				if(c=='#')
					state=SEG_TAILEND;
				else if(c != '!')
					state=SEG_TAIL1;
				break;
			}
			default:
				break;
		}
	}
	return ret;
}


int recv_data(int connection,char* data,int length){
	char buf[MAX_BUF_LEN]={0};
	int ret=1;
	ret=recv_head(connection);
	ret=recv(connection,buf,length,0);
	ret=recv_tail(connection);

	if(ret < 0)
		concurrent_printf("connection interrupted!\n");
	else 
		memcpy(data,buf,length);
	return ret;
}